<?php

namespace common\service\project_warning_rules;

use common\service\EntityService;
use support\ErrorCode;
use support\SingletonTrait;
use common\model\EntityModel;
use common\service\OptionsService;
use common\exception\LogicException;

/**
 * 剧集最大资产数和镜头数检查
 */
class EpisodeAssetShotNumberCheck implements ProjectWarningRuleInterface
{

    const CHECK_CODE = 'EPISODE_ASSET_SHOT_NUMBER_CHECK';

    const NEED_PARAM = ['project_id'];

    use SingletonTrait;

    const EPISODE_DESIGN_ALLOW_MAX_NUMBER = 'episode_design_max_number';
    const EPISODE_STORYBOARD_ALLOW_MAX_NUMBER = 'episode_shot_max_number';


    private $errorMessage = [];

    /**
     * 检查参数是否包含
     * @param $param
     * @return void
     */
    public function paramRequired($param)
    {
        foreach (self::NEED_PARAM as $paramKey) {
            if (!isset($param[$paramKey])) {
                throw new LogicException("param {$paramKey} needed", ErrorCode::DATA_INVALID);
            }
        }
    }

    /**
     * 检查是否满足
     * @param $checkData
     * @return bool
     * @throws \think\Exception
     */
    public function check($checkData)
    {
        $this->paramRequired($checkData);
        $projectId = $checkData['project_id'];

        $config = $this->getLimitNumber();

        $queryModuleId = [];
        $having = [];
        $designModuleId = module_by_code('design')['id'];
        $storyboardModuleId = module_by_code('storyboard')['id'];
        if (!empty($config[self::EPISODE_DESIGN_ALLOW_MAX_NUMBER]) && intval($config[self::EPISODE_DESIGN_ALLOW_MAX_NUMBER]) > 0) {
            $queryModuleId[] = $designModuleId;
            $having[] = '(e.module_id = ' . $designModuleId . ' and number > ' . $config[self::EPISODE_DESIGN_ALLOW_MAX_NUMBER] . ')';
        }
        if (!empty($config[self::EPISODE_STORYBOARD_ALLOW_MAX_NUMBER]) && intval($config[self::EPISODE_STORYBOARD_ALLOW_MAX_NUMBER]) > 0) {
            $queryModuleId[] = $storyboardModuleId;
            $having[] = '(e.module_id = ' . $storyboardModuleId . ' and number > ' . $config[self::EPISODE_STORYBOARD_ALLOW_MAX_NUMBER] . ')';
        }

        if (empty($queryModuleId)) {
            return true;
        }
        // 查询出没有播放的剧集
        $notShowEpisodeList = EntityService::getInstance()->getNotShowEpisodeList($projectId);

        if (empty($notShowEpisodeList)) {
            return true;
        }
        $episodeIdS = implode(',', array_column($notShowEpisodeList, 'id'));

        $episodeOverflowList = model(EntityModel::class)
            ->alias('e')
            ->join('(select distinct entity_id, episode_id from entity_episode_relation where project_id = ' . $projectId . ' ) as epr on epr.entity_id = e.id')
            ->where(['e.module_id' => ['IN', $queryModuleId], 'e.project_id' => $projectId, 'epr.episode_id' => ['IN', $episodeIdS]])
            ->group('epr.episode_id,e.module_id')
            ->field('count(e.id) as number, e.module_id,epr.episode_id')
            ->having(implode(' OR ', $having))
            ->select();
        if (empty($episodeOverflowList)) {
            return true;
        }

        $episodeList = array_column($notShowEpisodeList, 'code', 'id');

        $this->errorMessage = [];
        foreach ($episodeOverflowList as $overflowItem) {
            $episode = $episodeList[$overflowItem['episode_id']] ?? null;
            if (empty($episode)) {
                continue;
            }

            if ($overflowItem['module_id'] == $designModuleId) {
                $errorText = $episode . '的资产总量超过了' . $config[self::EPISODE_DESIGN_ALLOW_MAX_NUMBER];
            } else {
                $errorText = $episode . '的镜头总量超过了' . $config[self::EPISODE_STORYBOARD_ALLOW_MAX_NUMBER];
            }
            $this->errorMessage[] = $errorText;
        }


        return false;
    }

    /**
     * 限额
     * @return array
     */
    private function getLimitNumber()
    {
        return OptionsService::getInstance()->getOptionsConfigMultiItemData('project_warning_check', ['episode_design_max_number', 'episode_shot_max_number']);
    }

    /**
     * 获取错误信息
     * @return array
     */
    public function getErrorMessage()
    {
        return $this->errorMessage;
    }

    /**
     * @inheritDoc
     */
    public function getCheckCode()
    {
        return self::CHECK_CODE;
    }
}
